package profit

import (
	"context"
	"git.mycaigou.com/gfyx/common/tenant_db"
	"git.mycaigou.com/gfyx/common/usermetadata"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils"
	"github.com/google/uuid"
	"gorm.io/gorm"
	"strconv"
	"time"
)

type profitRepository struct {
	tenant_db.TenantDB
}

func NewProfitRepository() ProfitRepositoryIface {
	return &profitRepository{}
}

func (r *profitRepository) CreateProfit(ctx context.Context, po *GfyxProfitPo) (*GfyxProfitPo, error) {
	err := r.GetTenantDB(ctx).Table(po.TableName()).Create(po).Error
	return po, err
}

func (r *profitRepository) QueryAllEffectiveProfitList(ctx context.Context) ([]*GfyxProfitPo, error) {
	db := r.GetTenantDB(ctx).Table(GfyxProfitPo{}.TableName()).
		Where("start_time <= ? and end_time >= ? and is_deleted = 0", time.Now(), time.Now())

	var queryList []*GfyxProfitPo
	if err := db.Find(&queryList).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}
	return queryList, nil
}

func (r *profitRepository) QueryEffectiveProfitListByCondition(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*GfyxProfitPo, error) {
	db := r.GetTenantDB(ctx).Table(GfyxProfitPo{}.TableName()).Where(condition).
		Where("start_time <= ? and end_time >= ? and is_deleted = 0", time.Now(), time.Now())

	var count int64
	var queryList []*GfyxProfitPo
	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}
	if pageInfo != nil && pageInfo.Page > 0 && pageInfo.PageSize > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Find(&queryList).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, nil, nil
		}
		return 0, nil, err
	}
	return count, queryList, nil
}

func (r *profitRepository) ExistProfit(ctx context.Context, deliveryNo string, deliveryBatchNo string, deliveryAuthId string) (*GfyxProfitPo, error) {
	tenantsProfit := &GfyxProfitPo{}
	err := r.GetTenantDB(ctx).
		Table(GfyxProfitPo{}.TableName()).
		Where("is_deleted = ?", constants.IsDeletedFalse).
		Where("delivery_batch_no = ?", deliveryBatchNo).
		Where("delivery_auth_id = ?", deliveryAuthId).
		Where("delivery_no = ?", deliveryNo).
		Order("created_on desc").First(tenantsProfit).Error

	if err != nil && err != gorm.ErrRecordNotFound {
		return tenantsProfit, err
	}
	return tenantsProfit, nil
}

func (r *profitRepository) UpdateProfit(ctx context.Context, condition, updates map[string]interface{}) error {
	return r.GetTenantDB(ctx).Table(GfyxProfitPo{}.TableName()).Where(condition).Updates(updates).Error
}

func (r *profitRepository) CreateProfitAccount(ctx context.Context, po *GfyxProfitAccountPo) (*GfyxProfitAccountPo, error) {
	err := r.GetTenantDB(ctx).Table(po.TableName()).Create(po).Error
	return po, err
}

func (r *profitRepository) QueryProfitAccount(ctx context.Context) (*GfyxProfitAccountPo, error) {
	profitAccountPo := GfyxProfitAccountPo{}
	err := r.GetTenantDB(ctx).Table(profitAccountPo.TableName()).Where("is_deleted = 0").First(&profitAccountPo).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &profitAccountPo, nil
}

func (r *profitRepository) UpdateProfitAccount(ctx context.Context, condition, updates map[string]interface{}) error {
	return r.GetTenantDB(ctx).Table(GfyxProfitAccountPo{}.TableName()).Where(condition).Updates(updates).Error
}

func (r *profitRepository) CreateProfitProvince(ctx context.Context, po *GfyxProfitProvincePo) (*GfyxProfitProvincePo, error) {
	err := r.GetTenantDB(ctx).Table(po.TableName()).Create(po).Error
	return po, err
}

func (r *profitRepository) SaveProfitProvince(ctx context.Context, provinceCodes []string) error {
	metaUserInfo := usermetadata.GetMetaUserInfo(ctx)
	gfyxProfitProvinceList, err := r.QueryProfitProvinceList(ctx)
	if err != nil {
		return err
	}
	db := r.GetTenantDB(ctx).Begin()

	addProvinceCode, delProvinceCode := make([]string, 0), make([]string, 0)
	for _, provinceCode := range provinceCodes {
		isMatch := false
		for _, item := range gfyxProfitProvinceList {
			if provinceCode == item.ProvinceCode {
				isMatch = true
				break
			}
		}
		if !isMatch {
			addProvinceCode = append(addProvinceCode, provinceCode)
		}
	}
	for _, item := range gfyxProfitProvinceList {
		isMatch := false
		for _, provinceCode := range provinceCodes {
			if provinceCode == item.ProvinceCode {
				isMatch = true
				break
			}
		}
		if !isMatch {
			delProvinceCode = append(delProvinceCode, item.ProvinceCode)
		}
	}

	if len(delProvinceCode) > 0 {
		err := db.
			Table(GfyxProfitProvincePo{}.TableName()).
			Where("province_code in (?) and is_deleted = ?", delProvinceCode, constants.IsDeletedFalse).
			Updates(map[string]interface{}{
				"is_deleted":  1,
				"modified_on": time.Now(),
				"modified_by": metaUserInfo.UserId,
			}).Error
		if err != nil {
			db.Rollback()
			return err
		}
	}

	if len(addProvinceCode) > 0 {
		for _, provinceCode := range addProvinceCode {
			obj := &GfyxProfitProvincePo{
				ProvinceCode: provinceCode,
				CreatedOn:    time.Now(),
				CreatedBy:    strconv.Itoa(int(metaUserInfo.UserId)),
				ModifiedOn:   time.Now(),
				ModifiedBy:   strconv.Itoa(int(metaUserInfo.UserId)),
			}
			if err := db.Save(obj).Error; err != nil {
				db.Rollback()
				return err
			}
		}
	}

	// 建模表——设置（省份）数据权限
	gfyxPermtenantprovincePo := GfyxPermtenantprovincePo{}
	if err := db.Where("1=1").Delete(&gfyxPermtenantprovincePo).Error; err != nil {
		db.Rollback()
		return err
	}
	for _, provinceCode := range provinceCodes {
		err := db.Create(&GfyxPermtenantprovincePo{
			LatestModificationDate: time.Now(),
			ProvinceCode:           provinceCode,
			CreatedName:            "双写同步",
			CreatedTime:            time.Now(),
			ModifiedName:           "双写同步",
			ModifiedTime:           time.Now(),
			PermTenantProvinceGUID: uuid.New().String(),
			VersionNumber:          time.Now(),
		}).Error
		if err != nil {
			db.Rollback()
			return err
		}
	}

	db.Commit()
	return nil
}

func (r *profitRepository) QueryProfitProvinceList(ctx context.Context) ([]*GfyxProfitProvincePo, error) {
	var queryList []*GfyxProfitProvincePo
	err := r.GetTenantDB(ctx).Table(GfyxProfitProvincePo{}.TableName()).Where("is_deleted = 0").Find(&queryList).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}
	return queryList, nil
}

func (r *profitRepository) QueryProfitProvinceListV2(ctx context.Context) ([]string, error) {
	var provinceCodes []string
	err := r.GetTenantDB(ctx).Table("gfyx_permtenantprovince").Where("__IsDeleted = 0").Select("ProvinceCode").Pluck("ProvinceCode", &provinceCodes).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}
	return provinceCodes, nil
}

func (r *profitRepository) DeleteProfitProvince(ctx context.Context, condition map[string]interface{}) error {
	return r.GetTenantDB(ctx).Table(GfyxProfitProvincePo{}.TableName()).Where(condition).Updates(map[string]interface{}{"is_deleted": 1}).Error
}
